package org.newcih.thread;

import org.junit.Test;

import java.util.Random;
import java.util.concurrent.*;

/**
 * Callable接口类似于Runnable，但是Runnable不会返回结果，并且无法抛出返回结果的异常
 * Callalbe被线程执行后，可以返回值，这个返回值可以被Future拿到，即Future可以拿到异步执行任务的返回值
 */
public class CallableAndFuture {

    private static String string = "Hello";

    /**
     * FutureTask实现了两个接口，Runable和Future，所以既可以作为Runnable被线程执行，又可以作为Future得到Callable的返回值。
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test1() throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            Thread.sleep(3000);
            return new Random().nextInt(100);
        });
        new Thread(futureTask).start();

        System.out.println("before end");
        System.out.println("end : " + futureTask.get());
        System.out.println("after end");
    }


    @Test
    public void test11() throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(string::toUpperCase);
        new Thread(futureTask).start();

        System.out.println(futureTask.get());
    }

    /**
     * ExecutorService继承自Executor，目的是管理Thread对象，是JDK 5之后启动任务的首选方式
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test2() throws ExecutionException, InterruptedException {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        Future<Integer> future = threadPool.submit(() -> {
            Thread.sleep(3000);
            return new Random().nextInt(100);
        });

        System.out.println("before end");
        System.out.println("end : " + future.get());
        System.out.println("after end");
    }

    @Test
    public void test21() throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        FutureTask<String> futureTask = new FutureTask<String>(string::toLowerCase);
        executorService.submit(futureTask);

        System.out.println(futureTask.get());
    }

    /**
     * 执行多个带返回值的任务，并取得多个返回值
     *
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @Test
    public void test3() throws InterruptedException, ExecutionException {
        CompletionService<Integer> completionService = new ExecutorCompletionService<>(Executors.newCachedThreadPool());

        for (int i = 0; i < 5; i++) {
            final int taskID = i;
            completionService.submit(() -> taskID);
        }

        for (int i = 0; i < 5; i++) {
            System.out.println(completionService.take().get());
        }
    }

    @Test
    public void test31() throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        CompletionService<String> completionService = new ExecutorCompletionService<>(executorService);

//        executorService.submit(new FutureTask<>(string::toUpperCase));
//        executorService.submit(new FutureTask<>(string::toLowerCase));

        completionService.submit(string::toUpperCase);
        completionService.submit(string::toLowerCase);

        for (int i = 0; i < 2; i++) {
            System.out.println(completionService.take().get());
        }

    }

}
